public class Main{
	public static void main(String[] args){
		//switch语句根据switch (表达式)计算的结果，跳转到匹配的case结果，然后继续执行后续语句，直到遇到break结束执行。
		int option = 1;

		switch(option) {
			case 1:
				System.out.println("Select 1");
				break;
			case 2:
				System.out.println("Select 2");
				break;
			case 3:
				System.out.println("Select 3");
				break;
		}
		//修改option的值分别为1、2、3，观察执行结果。

		//如果option的值没有匹配到任何case，例如option = 99，那么，switch语句不会执行任何语句。这时，可以给switch语句加一个default，当没有匹配到任何case时，执行default
		int option = 99;
        switch (option) {
	        case 1:
	            System.out.println("Selected 1");
	            break;
	        case 2:
	            System.out.println("Selected 2");
	            break;
	        case 3:
	            System.out.println("Selected 3");
	            break;
	        default:
	        	System.out.println("Not selected");
	        	break;
        }

        //如果把switch语句翻译成if语句，那么上述的代码相当于:
        if (option == 1) {
            System.out.println("Selected 1");
        } else if (option == 2) {
            System.out.println("Selected 2");
        } else if (option == 3) {
            System.out.println("Selected 3");
        } else {
            System.out.println("Not selected");
        }

        /*
        对于多个==判断的情况，使用switch结构更加清晰。

        同时注意，上述“翻译”只有在switch语句中对每个case正确编写了break语句才能对应得上。

        使用switch时，注意case语句并没有花括号{}，而且，case语句具有“穿透性”，'漏写break'将导致意想不到的结果
        */
        int option = 2;
        switch (option) {
        case 1:
            System.out.println("Selected 1");
        case 2:
            System.out.println("Selected 2");
        case 3:
            System.out.println("Selected 3");
        default:
            System.out.println("Not selected");
        }
        //当option = 2时，将依次输出"Selected 2"、"Selected 3"、"Not selected"，原因是从匹配到case 2开始，后续语句将全部执行，直到遇到break语句。因此，任何时候都不要忘记写break。

        //如果有几个case语句执行的是同一组语句块，可以这么写
        int option = 2;

        switch (option) {
        case 1:
            System.out.println("Selected 1");
            break;
        case 2:
        case 3:
            System.out.println("Selected 2, 3");
            break;
        default:
            System.out.println("Not selected");
            break;
        }

        //使用switch语句时，只要保证有break，case的顺序不影响程序逻辑：
        switch (option) {
        case 3:
            ...
            break;
        case 2:
            ...
            break;
        case 1:
            ...
            break;
        }

        //switch语句还可以匹配字符串。字符串匹配时，是比较“内容相等”。
        String fruit = "apple";

        switch (fruit) {
        case "apple":
            System.out.println("Selected apple");
            break;
        case "pear":
            System.out.println("Selected pear");
            break;
        case "mango":
            System.out.println("Selected mango");
            break;
        default:
            System.out.println("No fruit selected");
            break;
        }

        //switch语句还可以使用枚举类型，枚举类型我们在后面讲解。

        //switch表达式
		//使用switch时，如果遗漏了break，就会造成严重的逻辑错误，而且不易在源代码中发现错误。从Java 12开始，switch语句升级为更简洁的‘表达式语法’

		//使用类似模式匹配（Pattern Matching）的方法，保证只有一种路径会被执行，并且不需要break语句：
		String fruit = "apple";

        switch (fruit) {
        case "apple" -> System.out.println("Selected apple");
        case "pear" -> System.out.println("Selected pear");
        case "mango" -> {
            System.out.println("Selected mango");
            System.out.println("Good choice!");
        }
        default -> System.out.println("No fruit selected");
        }

        //注意新语法使用->，如果有多条语句，需要用{}括起来。不要写break语句，因为新语法只会执行匹配的语句，没有穿透效应。
        // 很多时候，我们还可能用switch语句给某个变量赋值。
        int opt;

        switch (fruit) {
        case "apple":
            opt = 1;
            break;
        case "pear":
        case "mango":
            opt = 2;
            break;
        default:
            opt = 0;
            break;
        }

        //使用新的switch语法，不但不需要break，还可以直接返回值。把上面的代码改写如下
        String fruit = "apple";

        int opt = switch (fruit) {
            case "apple" -> 1;
            case "pear", "mango" -> 2;
            default -> 0;
        }; // 注意赋值语句要以;结束

        System.out.println("opt = " + opt);


        // yield
        //大多数时候，在switch表达式内部，我们会返回简单的值。如果需要复杂的语句，我们也可以写很多语句，放到{...}里，
        //然后用yield返回一个值作为switch语句的返回值：
        String fruit = "orange";

        int opt = switch (fruit) {
            case "apple" -> 1;
            case "pear", "mango" -> 2;
            default -> {
                int code = fruit.hashCode();
                yield code; // switch语句返回值
            }
        };
        System.out.println("opt = " + opt);

	}
}

/*
除了if语句外，还有一种条件判断，是根据某个表达式的结果，分别去执行不同的分支。

例如，在游戏中，让用户选择选项：

单人模式
多人模式
退出游戏
这时，switch语句就派上用场了。

*/

/*
编译检查
使用IDE时，可以自动检查是否漏写了break语句和default语句，方法是'打开IDE的编译检查'。

在Eclipse中，选择'Preferences - Java - Compiler - Errors/Warnings - Potential programming problems'，将以下检查标记为Warning：

'switch' is missing 'default' case
'switch' case fall-through
在Idea中，选择'Preferences - Editor - Inspections - Java - Control flow issues'，将以下检查标记为Warning：

Fallthrough in 'switch' statement
'switch' statement without 'default' branch
当switch语句存在问题时，即可在IDE中获得警告提示。

! ! !  switch(option){...}
1.不要忘记break
2.不要忘记default
3.case 1: 不需要{}
！！！
*/




/* 小结
switch语句可以做多重选择，然后执行匹配的case语句后续代码；

switch的计算结果‘必须’是‘整型、字符串或枚举类型’；

注意千万不要漏写break，建议打开fall-through警告；

总是写上default，建议打开missing default警告；

从Java 14开始，switch语句正式升级为表达式，不再需要break，并且允许使用yield返回值。
*/